package Prova::Controller::DataBlock;

use strict;
use warnings;
use base 'Catalyst::Controller';
use Prova::Tests;
use Prova::Operations;
use Prova::Checksum;
use Data::Dumper;
use YAML;

=head1 NAME

Prova::Controller::DataBlock - Catalyst Controller

=head1 DESCRIPTION

Catalyst Controller.

=head1 METHODS

=cut

=head2 default

default action

=cut

sub default : Private {
    my ( $self, $c ) = @_;

    $c->response->body('Matched Prova::Controller::DataBlock in DataBlock.');
}

=head2 add

add action

=cut

sub add : Local {
    my ( $self, $c ) = @_;

    $c->stash->{is_add}   = 1;
    $c->stash->{template} = 'datablock/edit.tt';
    $c->stash->{action}   = 'add';
    $c->stash->{tests}    = [ Prova::Tests::types() ];

    my $test_case_id = $c->req->param('test_case_id');
    my $testcase = $c->model('DBIC::TestCase')->search( id => $test_case_id )->first;
    $c->stash->{test_case_id} = $testcase->id;

    if ( $c->request->method eq 'POST' ) {
        my $params = $c->req->params;
        $c->stash->{testcase} = $testcase;
        $c->stash->{data}     = {
            method  => $params->{method}  || undef,
            engine  => $params->{engine}  || undef,
            path    => $params->{path},
            runtime => $params->{runtime} || undef,
            description => $params->{description},
        };
        $c->forward('create');

        my $datablock = $c->stash->{datablock};
        $c->forward( 'update', [ ( $datablock, $params ) ] );

        if ( $c->req->param('return_path') ) {
            $c->res->redirect( '/' . $c->req->param('return_path') );
        } else {
            $c->res->redirect( '/testcase/edit/' . $datablock->test_case_id->checksum );
        }
    }

    # accessors in same testcase
    $c->forward( '/accessor/get_testcase_accessors', [ $testcase->id ] ) if $testcase;
}

=head2 edit

edit action

=cut

sub edit : Local {
    my ( $self, $c, $checksum ) = @_;

    $c->log->debug( "===== checksum : " . $checksum );
    $c->stash->{template} = 'datablock/edit.tt';
    $c->stash->{action}   = 'edit' unless $c->stash->{action};
    $c->stash->{tests}    = [ Prova::Tests::types() ];

    # data block
    my $datablock = $c->model('DBIC::DataBlock')->search( checksum => $checksum )->first;
    $c->detach('/pagenotfound/publish') unless $datablock;
    $c->stash->{query_hash} = Load $datablock->query  if($datablock->query);
    $c->stash->{datablock} = $datablock;

    # data section
    $c->stash->{datasection} = $c->forward( '/datasection/find_by_id', [ ( $datablock->id ) ] );

    # file
    $c->stash->{files} = $c->forward( '/file/find_by_id', [ ( $datablock->id ) ] );

    # assertion
    $c->stash->{tests} = [ Prova::Tests::types() ];
    my @assertion = $c->model('DBIC::Assertion')->search( data_block_id => $datablock->id );
    $c->stash->{assertion} = \@assertion if @assertion;

    # operation
    $c->stash->{operations} = [ Prova::Operations::types($c) ];
    my @pre_operation = $c->model('DBIC::PreOperation')->search( data_block_id => $datablock->id );
    $c->stash->{pre_operation} = \@pre_operation if @pre_operation;
    my @post_operation = $c->model('DBIC::PostOperation')->search( data_block_id => $datablock->id );
    $c->stash->{post_operation} = \@post_operation if @post_operation;

    # accessor
    my @accessor = $c->model('DBIC::Accessor')->search( data_block_id => $datablock->id );
    $c->stash->{accessor} = \@accessor if @accessor;

    my $method = $c->request->method;
    $c->log->debug( '===== method : ' . $method );

    if ( $method eq 'POST' ) {

        # CHECK ERRORS

        my $params = $c->req->params;

        $c->stash->{datablock} = $datablock;
        $c->forward( 'update', [ ( $datablock, $params ) ] );

        $c->stash->{status}    = 1;
        $c->stash->{datablock} = $datablock;

        my $url = $datablock->test_case_id->is_recording ? '/testcase/recording' : '/testcase/edit/' . $datablock->test_case_id->checksum;
        $c->res->redirect($url);
    }

    # accessors in same testcase
    $c->forward( '/accessor/get_testcase_accessors', [ $datablock->test_case_id->id ] );
}

=head2 update

internal update action

=cut

sub update : Private {
    my ( $self, $c, $datablock, $params ) = @_;

    my $runtime = ( $params->{'runtime'} =~ /^(\d+)$/ && $params->{'runtime'} != 0 ) ? $params->{'runtime'} : undef;

    # datablock
    $datablock->method( $params->{'method'} );
    $datablock->engine( $params->{'engine'} );
    $datablock->path( $params->{'path'} );
    $datablock->encode( $params->{'encode'} );
    $datablock->description( $params->{'description'} );
    $datablock->runtime($runtime);
    $datablock->update;
    $c->stash->{datablock} = $datablock;

    # datasection
    my %datasection;
    my %assertion;
    my %pre_operation;
    my %post_operation;
    my %accessor;
    if ( ref $params eq 'HASH' ) {
        for ( keys %$params ) {
            if ( $_ =~ /datasection\.(-?\d+)\.name/ ) {
                $datasection{$1} = {
                    name  => $params->{$_},
                    value => $params->{"datasection.$1.value"}
                } if $params->{"datasection.$1.value"};
            }
            elsif ( $_ =~ /assertion\.(-?\d+)\.command/ ) {
                $assertion{$1} = {
                    command => $params->{$_},
                    value   => $params->{"assertion.$1.value"}
                } if $params->{"assertion.$1.value"};
            }
            elsif ( $_ =~ /pre_operation\.(-?\d+)\.command/ ) {
                $pre_operation{$1} = {
                    command => $params->{$_},
                    value   => $params->{"pre_operation.$1.value"}
                } if $params->{"pre_operation.$1.value"};
            }
            elsif ( $_ =~ /post_operation\.(-?\d+)\.command/ ) {
                $post_operation{$1} = {
                    command => $params->{$_},
                    value   => $params->{"post_operation.$1.value"}
                } if $params->{"post_operation.$1.value"};
            }
            elsif ( $_ =~ /accessor\.(-?\d+)\.name/ ) {
                $accessor{$1} = {
                    name  => $params->{$_},
                    alias => $params->{"accessor.$1.alias"}
                  } if $params->{$_}
                  or $params->{"accessor.$1.alias"};
            }
        }
    }

    $c->stash->{datasection} = \%datasection;
    $c->forward('/datasection/create');

    $c->stash->{assertion} = \%assertion;
    $c->forward('/assertion/create');

    $c->stash->{pre_operation} = \%pre_operation;
    $c->forward('/preoperation/create');

    $c->stash->{post_operation} = \%post_operation;
    $c->forward('/postoperation/create');

    $c->stash->{accessor} = \%accessor;
    $c->forward('/accessor/create');
}

=head2 find_by_id

get datablock model objects from testcase_id

=cut

sub find_by_id : Private {
    my ( $self, $c, $testcase_id ) = @_;

    my $datablock = [ $c->model('DBIC::DataBlock')->search( { test_case_id => $testcase_id }, { order_by => 'order_by' } ) ];

    return $datablock;
}

=head2 create

internal create action

=cut

sub create : Private {
    my ( $self, $c ) = @_;

    my $testcase = $c->stash->{testcase};
    my $data     = $c->stash->{data};

    if ( ref $data eq 'HASH' ) {
        $data->{test_case_id} = $testcase->id;

        # order_by
        my ($rec_datablock) = $c->model('DBIC::DataBlock')->search( { test_case_id => $testcase->id }, { order_by => 'order_by desc' } )->first;
        $data->{order_by} = $rec_datablock ? $rec_datablock->order_by + 1 : 1;

        # checksum
        $data->{checksum} = Prova::Checksum->calc( $data->{path} );

        my $datablock = $c->model('DBIC::DataBlock')->create($data);
        $c->log->info( "create data_block : id=" . $datablock->id );
        $c->stash->{datablock} = $datablock;
    }
}

=head2 delete

delete action

=cut

sub delete : Local {
    my ( $self, $c, $checksum ) = @_;

    $c->log->debug( "=== " . $checksum );
    my $datablock = $c->model('DBIC::DataBlock')->search( checksum => $checksum )->first;
    my $testcase_checksum;
    if ( $datablock ){
        $testcase_checksum = $datablock->test_case_id->checksum;
        $datablock->delete($c);
    }
    if ( $c->req->param('return_path') ) {
        $c->res->redirect( '/' . $c->req->param('return_path') );
    } else {
        $c->res->redirect( '/testcase/edit/' . $testcase_checksum );
    }
}

=head1 AUTHOR

Shanon Inc, E<lt>http://www.shanon.co.jp/E<gt>

=head1 LICENSE

This library is free software, you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

1;
